<template>
  <div>
    <slot name="paper" :content="content"></slot>
  </div>
</template>

<script setup>
import { ref, watch, onMounted, onBeforeUnmount } from 'vue';

const props = defineProps({
  printerInfo: {
    type: String,
    default: ''
  },
  duration: {
    type: Number,
    default: 100
  },
  delay: {
    type: Number,
    default: 3000
  },
  working: {
    type: Boolean,
    default: true
  },
  once: {
    type: Boolean,
    default: false
  }
});

const content = ref('');
const cursor = ref(0);
const timer = ref(null);
const timeout = ref(null);
const print = ref(true);

const work = () => {
  let currentCursor = cursor.value;
  currentCursor += print.value ? 1 : -1;
  if (print.value) {
    if (currentCursor === props.printerInfo.length + 1) {
      currentCursor -= 2;
      print.value = !print.value;
    }
  } else {
    if (currentCursor === -1) {
      currentCursor += 2;
      print.value = !print.value;
    }
  }
  cursor.value = currentCursor;
};

const start = (work) => {
  timeout.value = setTimeout(() => {
    timer.value = setInterval(() => {
      work();
      if (
        cursor.value === 0 ||
        (cursor.value === props.printerInfo.length && !props.once)
      ) {
        clearInterval(timer.value);
        start(work);
      } else if (cursor.value === props.printerInfo.length && props.once) {
        clearInterval(timer.value);
      }
    }, props.duration);
  }, props.delay);
};

const toBegin = () => {
  cursor.value = 0;
  if (timeout.value !== null) {
    clearTimeout(timeout.value);
    if (timer.value !== null) {
      clearInterval(timer.value);
    }
  }
  if (props.working) {
    start(work);
  } else {
    content.value = props.printerInfo;
  }
};

onMounted(() => {
  if (props.working) {
    start(work);
  } else {
    content.value = props.printerInfo;
  }
});

onBeforeUnmount(() => {
  clearInterval(timer.value);
});

watch([() => props.working, () => props.printerInfo], () => {
  toBegin();
});

watch(cursor, (newCursor) => {
  content.value = props.printerInfo.slice(0, newCursor);
});
</script>
